package com.dj.ms.session;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.useragent.*;
import com.alibaba.fastjson.JSONObject;
import com.dj.common.constants.ResponseStatus;
import com.dj.common.exception.CentralException;
import com.dj.common.lang.utils.ServerHostUtils;
import com.dj.ms.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * <br>
 * <p>Principal</p>
 *
 * <br>
 *
 * @author ZJG
 * @version 1.0
 * @date 2021/8/4 下午2:29
 */
@Slf4j
public final class PrincipalHandler {

    private static final String[] locals = new String[]{"127.0.0.1", "localhost"};
    private static final String[] ignore_env = new String[]{"dev"};

    public static Principal buildSessionSerializable(HttpServletRequest request, String activeProfiles, boolean isUnAuth) throws Exception {
        Principal build = buildPrincipal(request);
        log.info("session principal info:{}", JSONObject.toJSONString(build));

        //本地及测试环境屏蔽校验异常
        StringBuffer url = request.getRequestURL();
        String domainInfo = url.delete(url.length() - request.getRequestURI().length(), url.length()).append("/").toString();
        if (StringUtils.isBlank(build.getUserId())
                && !StringUtils.containsAny(domainInfo, locals)
                && !StringUtils.containsAny(activeProfiles, ignore_env)
                && !isUnAuth) {
            log.error("build session serializable error, user authorization failed. 用户授权失败");
            throw new CentralException(ResponseStatus.HTTP_UNAUTHORIZED, "用户授权失败, 未获取到用户信息");
        }

        return build;
    }

    public static Principal buildSessionSerializableNoEx(HttpServletRequest request) throws Exception {
        return buildPrincipal(request);
    }

    public static String buildPairKey(Principal principal) {
        if (StrUtil.isNotBlank(principal.getUserId())) {
            return principal.getUserId();
        }
        return principal.getBizUnit() + "_"
                + principal.getDomainChannel() + "_"
                + principal.getIp() + "_"
                + principal.getDevice() + "_"
                + principal.getOs() + "_"
                + principal.getOsVersion() + "_"
                + principal.getBrowser() + "_"
                + principal.getBrowserVersion() + "_"
                + principal.getRenderEngine() + "_"
                + principal.getRenderEngineVersion()+"_";
    }

    public static String parseUserCode(HttpServletRequest request) throws Exception {
        String accountId = request.getHeader("accountId");
        if (StrUtil.isBlank(accountId)) {
            accountId = request.getHeader("uid");
        }
        if (StrUtil.isBlank(accountId)) {
            String bu = URLUtil.decode(request.getHeader("bu"), "UTF-8");
            String sc = URLUtil.decode(request.getHeader("sc"), "UTF-8");
            Principal principal = new Principal();
            principal.setIp(ServerHostUtils.getIp(request));
            userAgent(request, principal);
            accountId = bu + "_"
                    + sc + "_"
                    + principal.getIp() + "_"
                    + principal.getDevice() + "_"
                    + principal.getOs() + "_"
                    + principal.getOsVersion() + "_"
                    + principal.getBrowser() + "_"
                    + principal.getBrowserVersion() + "_"
                    + principal.getRenderEngine() + "_"
                    + principal.getRenderEngineVersion()+"_";
        }
        return accountId;
    }

    private static Principal buildPrincipal(HttpServletRequest request) {
        String userId = request.getHeader("accountId");
        if (StrUtil.isBlank(userId)) {
            userId = request.getHeader("uid");
        }
        String userName = URLUtil.decode(request.getHeader("account"), "UTF-8");
        if (StrUtil.isBlank(userName)) {
            userName = URLUtil.decode(request.getHeader("uname"), "UTF-8");
        }
        String phone = URLUtil.decode(request.getHeader("phone"), "UTF-8");
        String merchantId = request.getHeader("merchantId");
        String companyId = request.getHeader("companyId");
        String departmentId = request.getHeader("departmentId");
        String merchantName = URLUtil.decode(request.getHeader("merchantName"), "UTF-8");
        String companyName = URLUtil.decode(request.getHeader("companyName"), "UTF-8");
        String departmentName = URLUtil.decode(request.getHeader("departmentName"), "UTF-8");
        //业务单元
        String bu = URLUtil.decode(request.getHeader("bu"), "UTF-8");
        //系统通道
        String sc = URLUtil.decode(request.getHeader("sc"), "UTF-8");
        String ip = URLUtil.decode(request.getHeader("access-ip"), "UTF-8");
        //客户端来源
        String clientSource = URLUtil.decode(request.getHeader("clientSource"), "UTF-8");
        if (StrUtil.isBlank(ip)) {
            ip = ServerHostUtils.getIp(request);
        }
        if (StrUtil.isBlank(ip)) {
            ip = IpUtils.getIpAddress(request);
        }

        Principal build = Principal.builder()
                .userId(userId)
                .userName(userName)
                .bizUnit(bu)
                .domainChannel(sc)
                .merchantId(merchantId)
                .merchantName(merchantName)
                .companyId(companyId)
                .companyName(companyName)
                .departmentId(departmentId)
                .departmentName(departmentName)
                .ip(ip)
                .phone(phone)
                .clientSource(clientSource)
                .build();
        userAgent(request, build);
        return build;
    }

    private static void userAgent(HttpServletRequest request, Principal principal) {
        String userAgentString = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgentUtil.parse(userAgentString);
        Browser browser = userAgent.getBrowser();
        if (ObjectUtil.isNotNull(browser)) {
            principal.setBrowser(browser.getName());
            principal.setBrowserVersion(browser.getVersion(userAgentString));
        }
        OS os = userAgent.getOs();
        if (ObjectUtil.isNotNull(os)) {
            principal.setOs(os.getName());
            principal.setOsVersion(userAgent.getOsVersion());
        }
        Platform platform = userAgent.getPlatform();
        if (ObjectUtil.isNotNull(platform)) {
            principal.setDevice(platform.getName());
            principal.setDeviceType(platform.isMobile() ? "mobile" : "pc");
        }
        Engine engine = userAgent.getEngine();
        if (ObjectUtil.isNotNull(engine)) {
            principal.setRenderEngine(engine.getName());
            principal.setRenderEngineVersion(userAgent.getEngineVersion());
        }
        //app类型
        String at = URLUtil.decode(request.getHeader("at"), "UTF-8");
        principal.setAppType(at);
    }

}
